// ------------------------------------------------------------------------------
// 
// Copyright (c) 2006-2008 Swampware, Inc.
// 
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// 
// ------------------------------------------------------------------------------
using System;

namespace Water.Commands
{
	/// <summary>
	/// Summary description for PrintCommand.
	/// </summary>
	public class PrintCommand : Water.Commands.Command
	{

		public PrintCommand()
		{
		}

		public override string Name
		{
			get { return "print"; }
		}

		public override object Evaluate(Water.List expressions, Water.Environment environment, Water.Evaluator evaluator)
		{
			if(expressions.Count != 1)
			{
				throw new Water.Commands.InvalidArgumentsException(this.Name, expressions);
			}


			object result = evaluator.Evaluate(expressions[0], environment);

			if(result is byte)
			{
				Water.Output.WriteLine(result.ToString());
			}
			else if(result is byte[])
			{
				byte[] array = (byte[])result;

				for(int i = 0; i < array.Length; i++)
				{
					if(i > 0)
					{
						Water.Output.Write(" ");
					}
					Water.Output.Write(array[i].ToString());
				}
				Water.Output.WriteLine();
			}
			else if(result is byte[,])
			{
				byte[,] matrix = (byte[,])result;

				for(int y = 0; y < matrix.GetLength(1); y++)
				{
					for(int x = 0; x < matrix.GetLength(0); x++)
					{
						if(x > 0)
						{
							Water.Output.Write("\t");
						}
						Water.Output.Write(matrix[x,y].ToString());
					}
					Water.Output.WriteLine();
				}
			}
			else if(result is short)
			{
				Water.Output.WriteLine(result.ToString());
			}
			else if(result is short[])
			{
				short[] array = (short[])result;

				for(int i = 0; i < array.Length; i++)
				{
					if(i > 0)
					{
						Water.Output.Write(" ");
					}
					Water.Output.Write(array[i].ToString());
				}
				Water.Output.WriteLine();
			}
			else if(result is short[,])
			{
				short[,] matrix = (short[,])result;

				for(int y = 0; y < matrix.GetLength(1); y++)
				{
					for(int x = 0; x < matrix.GetLength(0); x++)
					{
						if(x > 0)
						{
							Water.Output.Write("\t");
						}
						Water.Output.Write(matrix[x,y].ToString());
					}
					Water.Output.WriteLine();
				}
			}
			else if(result is int)
			{
				Water.Output.WriteLine(result.ToString());
			}
			else if(result is int[])
			{
				int[] array = (int[])result;

				for(int i = 0; i < array.Length; i++)
				{
					if(i > 0)
					{
						Water.Output.Write(" ");
					}
					Water.Output.Write(array[i].ToString());
				}
				Water.Output.WriteLine();
			}
			else if(result is int[,])
			{
				int[,] matrix = (int[,])result;

				for(int y = 0; y < matrix.GetLength(1); y++)
				{
					for(int x = 0; x < matrix.GetLength(0); x++)
					{
						if(x > 0)
						{
							Water.Output.Write("\t");
						}
						Water.Output.Write(matrix[x,y].ToString());
					}
					Water.Output.WriteLine();
				}
			}
			else if(result is long)
			{
				Water.Output.WriteLine(result.ToString());
			}
			else if(result is long[])
			{
				long[] array = (long[])result;

				for(int i = 0; i < array.Length; i++)
				{
					if(i > 0)
					{
						Water.Output.Write(" ");
					}
					Water.Output.Write(array[i].ToString());
				}
				Water.Output.WriteLine();
			}
			else if(result is long[,])
			{
				long[,] matrix = (long[,])result;

				for(int y = 0; y < matrix.GetLength(1); y++)
				{
					for(int x = 0; x < matrix.GetLength(0); x++)
					{
						if(x > 0)
						{
							Water.Output.Write("\t");
						}
						Water.Output.Write(matrix[x,y].ToString());
					}
					Water.Output.WriteLine();
				}
			}
			else if(result is float)
			{
				Water.Output.WriteLine(result.ToString());
			}
			else if(result is float[])
			{
				float[] array = (float[])result;

				for(int i = 0; i < array.Length; i++)
				{
					if(i > 0)
					{
						Water.Output.Write(" ");
					}
					Water.Output.Write(array[i].ToString());
				}
				Water.Output.WriteLine();
			}
			else if(result is float[,])
			{
				float[,] matrix = (float[,])result;

				for(int y = 0; y < matrix.GetLength(1); y++)
				{
					for(int x = 0; x < matrix.GetLength(0); x++)
					{
						if(x > 0)
						{
							Water.Output.Write("\t");
						}
						Water.Output.Write(matrix[x,y].ToString());
					}
					Water.Output.WriteLine();
				}
			}
			else if(result is double)
			{
				Water.Output.WriteLine(result.ToString());
			}
			else if(result is double[])
			{
				double[] array = (double[])result;

				for(int i = 0; i < array.Length; i++)
				{
					if(i > 0)
					{
						Water.Output.Write(" ");
					}
					Water.Output.Write(array[i].ToString());
				}
				Water.Output.WriteLine();
			}
			else if(result is double[,])
			{
				double[,] matrix = (double[,])result;

				for(int y = 0; y < matrix.GetLength(1); y++)
				{
					for(int x = 0; x < matrix.GetLength(0); x++)
					{
						if(x > 0)
						{
							Water.Output.Write("\t");
						}
						Water.Output.Write(matrix[x,y].ToString());
					}
					Water.Output.WriteLine();
				}
			}
			else if(result is decimal)
			{
				Water.Output.WriteLine(result.ToString());
			}
			else if(result is decimal[])
			{
				decimal[] array = (decimal[])result;

				for(int i = 0; i < array.Length; i++)
				{
					if(i > 0)
					{
						Water.Output.Write(" ");
					}
					Water.Output.Write(array[i].ToString());
				}
				Water.Output.WriteLine();
			}
			else if(result is decimal[,])
			{
				decimal[,] matrix = (decimal[,])result;

				for(int y = 0; y < matrix.GetLength(1); y++)
				{
					for(int x = 0; x < matrix.GetLength(0); x++)
					{
						if(x > 0)
						{
							Water.Output.Write("\t");
						}
						Water.Output.Write(matrix[x,y].ToString());
					}
					Water.Output.WriteLine();
				}
			}
			else if(result is string)
			{
				Water.Output.WriteLine((string)result);
			}
			else if(result is string[])
			{
				string[] array = (string[])result;

				for(int i = 0; i < array.Length; i++)
				{
					if(i > 0)
					{
						Water.Output.Write(" ");
					}
					Water.Output.Write(array[i]);
				}
				Water.Output.WriteLine();
			}
			else if(result is string[,])
			{
				string[,] matrix = (string[,])result;

				for(int y = 0; y < matrix.GetLength(1); y++)
				{
					for(int x = 0; x < matrix.GetLength(0); x++)
					{
						if(x > 0)
						{
							Water.Output.Write("\t");
						}
						if(matrix[x,y] == null)
						{
							Water.Output.Write("");
						}
						else
						{
							Water.Output.Write(matrix[x,y]);
						}
					}
					Water.Output.WriteLine();
				}
			}
			else if(result is System.DateTime)
			{
				Water.Output.WriteLine(result.ToString());
			}
			else if(result is System.Guid)
			{
				Water.Output.WriteLine(result.ToString());
			}
			else if(result is System.Type)
			{
				System.Type type = (System.Type)result;
				Water.Output.WriteLine(type.FullName);
			}
			else if(result is System.IO.Stream)
			{
				System.IO.Stream stream = (System.IO.Stream)result;

				long position = stream.Position;
				stream.Position = 0;

				System.IO.StreamReader reader = new System.IO.StreamReader(stream);
				Water.Output.WriteLine(reader.ReadToEnd());

				stream.Position = position;
			}
			else if(result is Water.Operator)
			{
				Water.Operator op = (Water.Operator)result;

				Water.Output.WriteLine(op.ToString());
			}
			else if(result is object[])
			{
				object[] array = (object[])result;

				for(int i = 0; i < array.Length; i++)
				{
					if(i > 0)
					{
						Water.Output.Write(" ");
					}
					Water.Output.Write(array[i].ToString());
				}
				Water.Output.WriteLine();
			}
			else if(result is object[,])
			{
				object[,] matrix = (object[,])result;

				for(int y = 0; y < matrix.GetLength(1); y++)
				{
					for(int x = 0; x < matrix.GetLength(0); x++)
					{
						if(x > 0)
						{
							Water.Output.Write("\t");
						}
						if(matrix[x,y] == null)
						{
							Water.Output.Write("null");
						}
						else
						{
							Water.Output.Write(matrix[x,y].ToString());
						}
					}
					Water.Output.WriteLine();
				}
			}
			else
			{
				Water.Output.WriteLine(Water.Generator.QuickGenerate(result, "\t", "\n"));
			}

			return null;
		}

	}
}
